<template>
	<view class="popup-container" v-if="visible">
		<view class="popup-mask" @click="handleMaskClick"></view>
		<view class="popup-content">
			<view class="money-view">
				<text class="input-icon">￥</text>
				<view class="text-container">
					<text class="input-content">{{ formatMoney(waitCalculateData)}}</text>
				</view>
			</view>
			<view class="btn-view">
				<view class="grid-item" @click="inputNumber('C')">C</view>
				<view class="grid-item" @click="inputNumber('÷')">÷</view>
				<view class="grid-item" @click="inputNumber('×')">×</view>
				<view class="grid-item" @click="inputNumber('delete')">删除</view>

				<view class="grid-item" @click="inputNumber('1')">1</view>
				<view class="grid-item" @click="inputNumber('2')">2</view>
				<view class="grid-item" @click="inputNumber('3')">3</view>
				<view class="grid-item" @click="inputNumber('-')">-</view>

				<view class="grid-item" @click="inputNumber('4')">4</view>
				<view class="grid-item" @click="inputNumber('5')">5</view>
				<view class="grid-item" @click="inputNumber('6')">6</view>
				<view class="grid-item" @click="inputNumber('+')">+</view>

				<view class="grid-item" @click="inputNumber('7')">7</view>
				<view class="grid-item" @click="inputNumber('8')">8</view>
				<view class="grid-item" @click="inputNumber('9')">9</view>
				<view class="grid-item span-two-rows" @click="exeCalculate">{{optBtnText}}</view>

				<view class="grid-item" @click="inputNumber('0')">0</view>
				<view class="grid-item" @click="inputNumber('00')">00</view>
				<view class="grid-item" @click="inputNumber('.')">.</view>
			</view>
		</view>
	</view>
</template>

<script setup>
	import {
		ref,
		watch
	} from 'vue';
	import {
		add,
		div,
		mul,
		sub
	} from '@/utils/math-utils.js';
	import {
		formatMoney,
		getLastNumberLength
	} from '@/utils/utils';

	// 定义组件的 props
	const props = defineProps({
		initNumber: {
			type: String,
			default: '0'
		}
	});

	// 定义 emit 事件
	const emit = defineEmits(['confirm', 'cancel']);

	const visible = ref(false); // 控制弹窗的显示状态
	const waitCalculateData = ref('0') // 待计算公式
	const optBtnText = ref('ok') // 计算器动态按钮【= 、ok】

	// 监听
	watch(
		[() => props.initNumber],
		([newInitNumber]) => {
			waitCalculateData.value = newInitNumber
		}
	);

	// 打开计算器弹窗
	const open = () => {
		visible.value = true;
		waitCalculateData.value = props.initNumber
	};

	// 关闭计算器弹窗
	const close = () => {
		visible.value = false;
		waitCalculateData.value = '0'
	};

	// 点击遮罩层关闭弹窗
	const handleMaskClick = () => {
		close();
		// 通过 emit 将‘取消’传递给父组件
		emit('cancel');
	};

	// 计算器键盘输入值
	const inputNumber = (value) => {
		let waitData = waitCalculateData.value

		if (value == 'C') {
			waitCalculateData.value = '0'
			checkAndChangeBtnText()
			return
		}

		if (value == '+' || value == '-' || value == '×' || value == '÷') {
			if (waitData.endsWith('+') || waitData.endsWith('-') || waitData.endsWith('×') || waitData.endsWith('÷')) {
				waitData = waitData.slice(0, waitData.length - 1)
				waitCalculateData.value = waitData + value
				checkAndChangeBtnText()
				return
			}
			waitCalculateData.value = waitData + value
			checkAndChangeBtnText()
			return
		}

		if (value == 'delete') {
			if (waitData.length > 1) {
				waitCalculateData.value = waitData.slice(0, waitData.length - 1)
				checkAndChangeBtnText()
				return
			}
			waitCalculateData.value = '0'
			checkAndChangeBtnText()
			return
		}

		if (value == '.') {
			if (waitData.endsWith('.')) {
				return
			}
			if (waitData.endsWith('+') || waitData.endsWith('-') || waitData.endsWith('×') || waitData.endsWith('÷')) {
				waitCalculateData.value = waitData + '0' + value
				return
			}
			let split = waitData.split('.')
			if (split.length > 1) {
				let last = split[split.length - 1]
				if (!last.includes('+') && !last.includes('-') && !last.includes('×') && !last.includes('÷')) {
					return
				}
			}
			waitCalculateData.value = waitData + value
			return
		}

		// 修正 '00' => '0'
		if (value == '00' && waitData == '0') {
			value = '0'
		}

		// 最终输入的计算公式
		if (waitData == '0') {
			waitData = value
		} else {
			waitData = waitData + value
		}

		// 限制小数点后不能超过3位数字
		let split = waitData.split('.')
		if (split.length > 1) {
			let endStr = split[split.length - 1]
			if (!endStr.includes('+') && !endStr.includes('-') && !endStr.includes('×') && !endStr.includes('÷')) {
				// 则为纯数字
				if (endStr.length > 3) {
					uni.showToast({
						icon: 'none',
						title: '最多3位小数'
					})
					return
				}
			}
		} else if (getLastNumberLength(waitData) > 15) {
			uni.showToast({
				icon: 'error',
				title: '金额上限15位'
			})
			return
		}

		waitCalculateData.value = waitData
		return
	}

	// 检查是否需要修改键盘确认按钮文字
	const checkAndChangeBtnText = () => {
		let waitData = waitCalculateData.value

		const numData = Number(waitData);
		let isNumber = !isNaN(numData) && typeof numData === 'number';

		if (isNumber) {
			optBtnText.value = 'ok'
		} else {
			optBtnText.value = '='
		}
	}

	// 点击 ok or = 按钮
	const exeCalculate = () => {
		let waitData = waitCalculateData.value
		if (waitData.endsWith('+') || waitData.endsWith('-') || waitData.endsWith('×') ||
			waitData.endsWith('÷') || waitData.endsWith('.')) {
			waitData = waitData.slice(0, waitData.length - 1)
		}

		let finalResult = "0"
		let opt = optBtnText.value
		if (opt == '=') {
			// 计算值
			finalResult = calculate(waitData)
			if (finalResult == 'Infinity' || finalResult == '-Infinity' || finalResult == 'NaN') {
				uni.showToast({
					icon: 'error',
					title: '方程式错误'
				})
				return
			}

			waitCalculateData.value = finalResult
			checkAndChangeBtnText()
		} else {
			// 不需要计算
			finalResult = add(waitData, '0')

			// 关闭计算器
			close();
			// 通过 emit 将‘计算结果’传递给父组件
			emit('confirm', finalResult);
		}
	};

	// 简单的四则运算解析（先乘除后加减）
	const calculate = (inputStr) => {
		const tokens = inputStr.match(/[\d.]+|[-+×÷]/g);
		if (tokens[0] == '-') {
			tokens[1] = '-' + tokens[1];
			tokens.splice(0, 1);
		}
		// 先处理乘法和除法
		for (let i = 0; i < tokens.length; i++) {
			if (tokens[i] == '×' || tokens[i] == '÷') {
				const operator = tokens[i];
				let result;

				if (operator == '×') {
					result = mul(tokens[i - 1], tokens[i + 1]);
				} else {
					result = div(tokens[i - 1], tokens[i + 1]);
				}

				// 替换计算结果
				tokens.splice(i - 1, 3, result);
				i -= 2; // 调整索引
			}
		}

		// 处理加法和减法
		let finalResult = tokens[0];
		for (let i = 1; i < tokens.length; i += 2) {
			const operator = tokens[i];
			const value = tokens[i + 1];

			if (operator == '+') {
				finalResult = add(finalResult, value);
			} else if (operator == '-') {
				finalResult = sub(finalResult, value);
			}
		}

		return finalResult;
	}

	// 暴露方法给父组件
	defineExpose({
		open,
		close
	});
</script>

<style scoped>
	.popup-container {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		display: flex;
		justify-content: center;
		align-items: center;
		z-index: 1000;
	}

	.popup-mask {
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		background-color: rgba(0, 0, 0, 0.2);
	}

	.popup-content {
		position: absolute;
		left: 0;
		bottom: 0;
		width: 100%;
		background-color: #fff;
		box-shadow: 0 0 20rpx 4rpx rgba(136, 136, 136, 0.2);
		animation: heightChange 0.2s linear;
	}

	@keyframes heightChange {
		0% {
			height: 0;
		}

		100% {
			height: 620rpx;
		}
	}

	.money-view {
		height: 120rpx;
		display: flex;
		align-items: center;
		border: 1rpx solid #ddd;
		box-sizing: border-box;
		padding: 0 40rpx 0 20rpx;
		gap: 6rpx;
	}

	.input-icon {
		font-size: 60rpx;
		font-weight: bold;
		color: rgba(7, 193, 96, 1);
	}

	.text-container {
		/* 从右到左布局 */
		direction: rtl;
		overflow: scroll;
		white-space: nowrap;
	}

	.input-content {
		padding-top: 8rpx;
		font-size: 60rpx;
		font-weight: bold;
		white-space: nowrap;
		color: rgba(7, 193, 96, 1);
		/* 确保内容按块级元素渲染 */
		display: inline-block;
		/* 恢复文字方向为从左到右 */
		direction: ltr;
	}

	.btn-view {
		display: grid;
		grid-template-columns: repeat(4, 1fr);
		grid-template-rows: repeat(5, 110rpx);
		width: 100%;
	}

	.grid-item {
		box-sizing: border-box;
		border: 1rpx solid #eee;
		font-size: 36rpx;
		display: flex;
		justify-content: center;
		align-items: center;
		background-color: #fff;
	}

	.grid-item:active {
		background-color: #eee;
	}

	.span-two-rows {
		font-size: 54rpx;
		background-color: rgba(7, 193, 96, 1);
		grid-column: 4 / 5;
		grid-row: 4 / 6;
	}

	.span-two-rows:active {
		background-color: rgba(5, 149, 72, 1.0)
	}
</style>